# Wei Jiang

from twisted.internet.protocol import Factory
from twisted.internet import reactor, protocol
from twisted.protocols.basic import LineReceiver
from twisted.internet.endpoints import TCP4ClientEndpoint

# a client protocol

class slaveClientCommand(LineReceiver):
    def __init__(self,factory):
        self.brokerServerCommands = factory.brokerServerCommands
        self.brokerServerMachineStates = factory.brokerServerMachineStates
        self.typeCode = factory.typeCode
        self.factory = factory
        self.brokerCommandCode = -1
        

    
    def connectionMade(self):
        self.factory.numCommandProtocols = self.factory.numCommandProtocols + 1
        print "There are currently",self.factory.numCommandProtocols,"open command connection"
        
        self.brokerCommandCode = 3
        print "Command Port: Sent:",self.brokerCommandCode,self.brokerServerCommands[self.brokerCommandCode]
        self.sendLine(str(self.brokerCommandCode))

        
    
    def lineReceived(self, line):
        brokerState = int(data.strip())
        print "broker state:",brokerState,self.brokerServerMachineStates[brokerState]
        if brokerState == 0:
            self.sendLine("a")
        elif brokerState == 1:
            self.sendLine("0")
        elif brokerState == 2:
            self.sendLine("3")
        elif brokerState == 6:
            self.transport.loseConnection()
    
    def connectionLost(self, reason):
        print "connection lost"
        self.factory.numCommandProtocols = self.factory.numCommandProtocols - 1
        print "There are currently",self.factory.numCommandProtocols,"open command connection"
                
class slaveClientData(protocol.Protocol):
    def __init__(self,factory):
        self.typeCode = factory.typeCode
        self.factory = factory
        

    def connectionMade(self):
        self.factory.numDataProtocols = self.factory.numDataProtocols + 1
        print "There are currently",self.factory.numDataProtocols,"open data connection"
        
        outgoingData = "a"
        print "Data Port: Sent:",outgoingData
        self.transport.write(outgoingData)
    
    def dataReceived(self, data):
        "As soon as any data is received, write it back."
        print "Server said:", data
    
    def connectionLost(self, reason):
        print "connection lost"
        self.factory.numDataProtocols = self.factory.numDataProtocols - 1
        print "There are currently",self.factory.numDataProtocols,"open data connection"
        reactor.stop()

class slaveClientFactory(Factory):
    def __init__(self, typeCode):
        
        self.typeCode = typeCode
        self.numCommandProtocols = 0
        self.numDataProtocols = 0
        self.brokerServerCommands = {0:"Subscribe", 1:"Unsubscribe", 2:"Status",3:"Init"}
        self.brokerServerMachineStates = {0:"GETNAME",1:"GETCOMMAND",2:"GETCHANNEL",3:"DELCHANNEL",4:"GETSTATUS",5:"BEGIN",6:"END"}
        

    def buildProtocol(self, addr):
        
        if self.typeCode == 0:
            return slaveClientCommand(self)
        elif self.typeCode == 1:
            return slaveClientData(self)



def gotProtocol(p):
    #print "Send:","a","to data port"
    if p.typeCode == 0:
        print "command:",p
        commandProtocolInstanceReference = p
    elif p.typeCode == 1:
        print "data:",p
        dataProtocolInstanceReference = p        
    else:
        print "typeCode NOT recognized."
    #p.transport.write("a")

#this slave factory can generate 2 kinds of products based on different type codes.
#typeCode: 0 for control port, 1 for data port
print "Program begins."
commandProtocolInstanceReference = None
dataProtocolInstanceReference = None

controlPort = 10876
controlPoint = TCP4ClientEndpoint(reactor,"localhost",controlPort)
commandPortFactory = slaveClientFactory(0)
deferredForCommandPort = controlPoint.connect(commandPortFactory)
deferredForCommandPort.addCallback(gotProtocol)

#create the corresponding data port instance.
dataPort = 10877
dataPoint = TCP4ClientEndpoint(reactor,"localhost",dataPort)
dataPortFactory = slaveClientFactory(1)
deferredForDataPort = dataPoint.connect(dataPortFactory)
deferredForDataPort.addCallback(gotProtocol)

reactor.run()
print "Program end."


